import { useReducer, Reducer } from "react";

const UNDO = "UNDO";
const REDO = "REDO";
const SET = "SET";
const RESET = "RESET";

type State<T> = {
  past: T[];
  present: T;
  future: T[];
};

type Action<T> = {
  newPresent?: T;
  type: typeof UNDO | typeof REDO | typeof SET | typeof RESET;
};

const reducer = <T>(state: State<T>, action: Action<T>): State<T> => {
  const { past, present, future } = state;
  const { newPresent } = action;

  switch (action.type) {
    case UNDO: {
      if (past.length === 0) return state;
      return {
        past: past.slice(0, -1),
        present: past[past.length - 1],
        future: [present, ...future],
      };
    }
    case "REDO": {
      if (future.length === 0) return state;
      return {
        past: [...past, future[0]],
        present: future[0],
        future: future.slice(1),
      };
    }
    case "RESET": {
      if (newPresent === undefined) return state;
      return {
        past: [],
        present: newPresent,
        future: [],
      };
    }
    case "SET": {
      if (newPresent === undefined) return state;
      return {
        past: [...past, present],
        present: newPresent,
        future: [],
      };
    }
    default:
      return state;
  }
};
export const useUndo = <T>(initialPresent: T) => {
  const initialState: State<T> = {
    past: [],
    present: initialPresent,
    future: [],
  };
  const [state, dispatch] = useReducer<Reducer<State<T>, Action<T>>>(
    reducer,
    initialState
  );
  const { past, future, present } = state;
  const canUndo = past.length !== 0;
  const canRedo = future.length !== 0;
  return { present, dispatch, canRedo, canUndo };
};
